using System;
using System.Collections.Specialized;
using System.Text;
using System.Web;

namespace Framework.Library.Core.Utils.Web
{
    public static class UrlUtils
    {
        public static string GetSchemeHostPort(Uri uri)
        {
            if (uri == null)
                throw new ArgumentNullException("uri");

            return uri.Scheme + "://" + uri.Host + ":" + uri.Port + "/";
        }

        /// <summary>
        /// Converts the speicified NameValueCollection to query string text.
        /// </summary>
        /// <param name="nameValues">The NameValueCollection to convert.</param>
        /// <returns></returns>
        public static string ToQueryString(NameValueCollection nameValues)
        {
            return ToQueryString(nameValues, false);
        }

        /// <summary>
        /// Converts the speicified NameValueCollection to query string text.
        /// </summary>
        /// <param name="nameValues">The NameValueCollection to convert.</param>
        /// <param name="encodeValues">if set to <c>true</c> the values are encoded.</param>
        /// <returns></returns>
        public static string ToQueryString(NameValueCollection nameValues, bool encodeValues)
        {
            if (nameValues == null)
                throw new ArgumentNullException("nameValues");

            var sb = new StringBuilder();

            foreach (string variableKey in nameValues.AllKeys)
            {
                string value = nameValues[variableKey];

                if (value != null)
                {
                    sb.Append(variableKey);
                    sb.Append("=");
                    sb.Append((encodeValues) ? HttpUtility.UrlEncode(value) : value);
                    sb.Append("&");
                }
            }

            // remove trailing &
            if (sb.Length > 0)
                sb.Length = sb.Length - 1;

            return sb.ToString();
        }

        /// <summary>
        /// Converts the speicified querystring to a NameValueCollection.
        /// </summary>
        /// <param name="queryString">The querystring to convert to a NameValueCollection.</param>
        /// <returns></returns>
        public static NameValueCollection FromQueryString(string queryString)
        {
            return FromQueryString(queryString, false);
        }

        /// <summary>
        /// Converts the speicified querystring to a NameValueCollection.
        /// </summary>
        /// <param name="queryString">The querystring to convert to a NameValueCollection.</param>
        /// <param name="decodeValues">if set to <c>true</c> the values are decoded.</param>
        /// <returns></returns>
        public static NameValueCollection FromQueryString(string queryString, bool decodeValues)
        {
            var nameValues = new NameValueCollection();

            if (queryString == null)
                throw new ArgumentNullException("querystring");

            // split querystring up into fragments
            string[] array = queryString.Split(new[] {'&', '='});

            // add to namevaluecollection
            for (int i = 0; i < array.Length - 1; i += 2)
            {
                string name = array[i];
                string value = array[i + 1];

                nameValues.Add(name, (decodeValues) ? HttpUtility.UrlDecode(value) : value);
            }

            return nameValues;
        }

        public static string UrlEncodeBase64(string base64Data)
        {
            return new string(UrlEncodeBase64(base64Data.ToCharArray()));
        }

        public static char[] UrlEncodeBase64(char[] base64Data)
        {
            for (int i = 0; i < base64Data.Length; i++)
            {
                switch (base64Data[i])
                {
                    case '+':
                        base64Data[i] = '@';
                        break;
                    case '/':
                        base64Data[i] = '$';
                        break;
                }
            }
            return base64Data;
        }

        public static string UrlDecodeBase64(string base64Data)
        {
            return new string(UrlDecodeBase64(base64Data.ToCharArray()));
        }

        public static char[] UrlDecodeBase64(char[] base64Data)
        {
            for (int i = 0; i < base64Data.Length; i++)
            {
                switch (base64Data[i])
                {
                    case '@':
                        base64Data[i] = '+';
                        break;
                    case '$':
                        base64Data[i] = '/';
                        break;
                }
            }
            return base64Data;
        }

        public static bool IsRelativeUrl(string virtualPath)
        {
            if (virtualPath.IndexOf(":") != -1)
                return false;

            return !IsRooted(virtualPath);
        }

        public static bool IsRooted(string basepath)
        {
            if (!string.IsNullOrEmpty(basepath) && (basepath[0] != '/'))
                return (basepath[0] == '\\');

            return true;
        }
    }
}